package com.mrd.spring.repository;

import com.mrd.exception.DeleteException;
import com.mrd.exception.QueryException;
import com.mrd.exception.SaveException;
import com.mrd.framework.ui.Jqgrid;
import com.mrd.framework.ui.filter.Filter;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * 自定义抽象 Created by winaya on 2016/8/8.
 */
@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
    /**
     * 通过jqgrid对象查询数据
     *
     * @param jqgrid jqgrid对象
     * @return 查询的结果
     */
    Page<T> findByJqgrid(Jqgrid jqgrid) throws QueryException;

    /**
     * 通过查询图和jqgrid对象查询数据
     *
     * @param jqgrid    jqgrid对象
     * @param graphName 查询图的名称
     * @return 查询的结果
     */
    Page<T> findByJqgrid(Jqgrid jqgrid, String graphName) throws QueryException;

    /**
     * 通过分页查询获取记录,不加入其他参数,当startIndex大于0时分页才会生效
     *
     * @param startIndex 开始序号
     * @param size       获取记录数量
     */
    List<T> findEntityByPage(int startIndex, int size) throws QueryException;

    /**
     * 根据指定hql来通过分页查询获取记录,当startIndex大于0时分页才会生效
     *
     * @param startIndex 开始序号
     * @param size       获取记录数量
     */
    List<T> findEntityByPage(final String hql, int startIndex, int size)
            throws QueryException;

    /**
     * 通过分页查询排序后的记录，当startIndex大于0时分页才会生效
     *
     * @param startIndex 开始序号
     * @param size       获取记录数
     * @param order      排序字段
     */
    List<T> findEntityByPage(int startIndex, int size, Sort.Order order)
            throws QueryException;

    /**
     * 通过jqgrid过滤对象过滤查询结果,当startIndex大于0时分页才会生效
     *
     * @param startIndex 分页起始值
     * @param size       分页大小
     * @param filter     过滤对象
     * @param order      排序对象 null为不排序
     */
    List<T> findEntityByFilter(int startIndex, int size, Filter filter, Sort.Order order)
            throws QueryException;

    /**
     * 返回总计记录数
     */
    int findEntityCount() throws QueryException;

    /**
     * 更加jqgrid过滤对象来查询记录数
     *
     * @param filter 过滤对象
     */
    int findEntityCount(Filter filter) throws QueryException;

    /**
     * 根据主键id查询记录
     */
    T findEntityById(ID id) throws QueryException;

    /**
     * 查找所有的记录
     */
    List<T> findAllEntity() throws QueryException;

    /**
     * 保存或者修改数据,具体是保存还是修改取决于entity的主键是否为空
     *
     * @param entity 需要保存的对象
     * @throws SaveException 保存中发生错误则抛出该异常
     */
    @Transactional(value="transactionManager")
    void saveOrupdate(T entity) throws SaveException;

    /**
     * 执行特定修改，如批量修改,参数修改为jqpl语句
     *
     * @throws SaveException 修改时发生错误则抛出此异常
     */
    int updateByHql(String jpql) throws SaveException;

    /**
     * 执行特定修改，如批量修改，使用sql
     *
     * @throws Exception 修改时发生错误则抛出此异常
     */
    int updateBySql(String sql) throws Exception;

    /**
     * 执行特定sql
     *
     * @param parameters 参数
     * @throws Exception 执行Sql时发生的异常
     */
    int excuteSql(String sql, Map<String, Object> parameters) throws Exception;


    /**
     * 删除对象，该方法用于处理如下情形：某些设置了非空字段的对象，在删除时需要加入非空字段的信息，那么调用该方法会先通过主键读取数据库的信息，然后进行删除
     *
     * @param entity          对象
     * @param findBeforDelete 在删除前是否先查询数据库获取对象
     * @throws DeleteException 删除过程中发生错误则抛出此异常
     */
    void delete(T entity, boolean findBeforDelete) throws DeleteException;

    /**
     * 根据字段名称删除对应数据
     *
     * @param column 字段名
     * @param value  字段值
     */
    int delete(String column, Object value) throws DeleteException;

    /**
     * 根据hql对数据进行删除操作
     *
     * @param hql    hql
     * @param values 参数名和参数值
     */
    int delete(String hql, Map<String, Object> values) throws DeleteException;

    /**
     * 根据指定hql查询分页记录,传入参数，当startIndex大于0时分页生效
     *
     * @param page 当前展示页
     */
    List<Object> findEntityByHql(String hql, int page, int size,
                                 Map<String, Object> parameters) throws QueryException;

    /**
     * 根据指定sql查询分页记录,传入参数，当startIndex大于0时分页生效
     */
    List<Object> findEntityBySql(String sql, int startIndex, int size,
                                 Map<String, Object> parameters) throws QueryException;

    /**
     * 根据hql查询分页记录,传入参数，当startIndex大于0时分页生效
     */
//    List<T> findEntityByHql(String hql, int startIndex, int size, Filter filters);

    /**
     * 通过filter删除数据
     */
    int deleteByFilter(Filter filter) throws DeleteException;

    /**
     * 批量添加数据
     */
    void saveEntities(List<T> entities) throws SaveException;

    /**
     * 批量添加数据
     */
    void saveOrUpdateEntities(List<T> entities) throws SaveException;

    /**
     * 根据指定SQL查询该Sql返回的记录数
     *
     * @param sql 查询数据的sql,不是查询记录数的sql
     */
    int findEntityCountBySql(String sql, Map<String, Object> parameters)
            throws QueryException;

    /**
     * 根据指定HQL查询该Hql返回的记录数
     *
     * @param jpql 查询数据的jpql,不是查询记录数的hql
     */
    int findEntityCountByHql(String jpql, Map<String, Object> parameters)
            throws QueryException;


    List<?> findListByHql(String queryHql, Object[] params) throws QueryException;
}
